//
//  LBBeautifulSkinFilter.mm
//  OpenGLGame
//
//  Created by Nguyen Cong Huy on 2/22/13.
//  Copyright (c) 2013 UIT. All rights reserved.
//

#include "LBBeautifulSkinFilter.h"
#include "LBUtils.h"
#include "LBGraphics.h"
#include "LBFaceSkinDetect.h"
#include "LBBilateralFilter.h"
#include "LBCombineTextureFilter.h"
#include "LBTexture.h"

LBBeautifulSkinFilter::LBBeautifulSkinFilter(){
    faceSkinDetectFilter = new LBFaceSkinDetect();
    bilateralFilter = new LBBilateralFilter();
    bilateralFilter->setBlurSize(0.8);
    combineTextureFilter = new LBCombineTextureFilter();
}

LBBeautifulSkinFilter::~LBBeautifulSkinFilter(){
    outputTexture = 0;
    DELETE_SAFELY(faceSkinDetectFilter);
    DELETE_SAFELY(bilateralFilter);
    DELETE_SAFELY(combineTextureFilter);
}

void LBBeautifulSkinFilter::setFaceBoundData(int numFace, float* faceBoundData){
    faceSkinDetectFilter->setFaceBoundData(numFace, faceBoundData);
    combineTextureFilter->setNumFace(numFace);
    if(texture != 0) calculateBlurSize();
}

void LBBeautifulSkinFilter::render(){
    faceSkinDetectFilter->render();
    bilateralFilter->render();
    combineTextureFilter->render();
    outputTexture = combineTextureFilter->getOutputTexture();
}

void LBBeautifulSkinFilter::setTexture(LBTexture* texture){
    this->texture = texture;
    faceSkinDetectFilter->setTexture(texture);
    bilateralFilter->setTexture(texture);
    if(faceSkinDetectFilter->getFaceBoundData() != 0) calculateBlurSize();
    combineTextureFilter->setBackgroundTexture(texture);
    combineTextureFilter->setTopTexture(bilateralFilter->getOutputTexture());
    combineTextureFilter->setMaskTexture(faceSkinDetectFilter->getOutputTexture());
}

void LBBeautifulSkinFilter::calculateBlurSize(){
    if(faceSkinDetectFilter->getNumFace() != 0){
        float minFaceWidthHeight = 10000;
        for (int i = 0; i < faceSkinDetectFilter->getNumFace(); i+=4) {
            float faceWidth = texture->getWidth();//faceSkinDetectFilter->getFaceBoundData()[i+2];
            float faceHeight = texture->getHeight();//faceSkinDetectFilter->getFaceBoundData()[i+3];
            float faceWidthHeight = faceWidth + faceHeight;
            if(faceWidthHeight < minFaceWidthHeight) minFaceWidthHeight = faceWidthHeight;
        }
        float blurSize = minFaceWidthHeight/1000;        //minFaceWidthHeight/1000;
        bilateralFilter->setBlurSize(blurSize);
        printf("Blur size: %f\n", blurSize);
        // note: faceWidth now is texture width
    }
}

void LBBeautifulSkinFilter::setAverageSkinColor(float red, float green, float blue){
    faceSkinDetectFilter->setAverageSkinColor(red, green, blue);
    combineTextureFilter->setAverageSkinColor(red, green, blue);
    
}

void LBBeautifulSkinFilter::setStandardBrightness(float standardBrightness){
    combineTextureFilter->setStandardBrightness(standardBrightness);
}

void LBBeautifulSkinFilter::setBlurSize(float blurSize){
    bilateralFilter->setBlurSize(blurSize);
}

float LBBeautifulSkinFilter::getBlurSize(){
    return bilateralFilter->getBlurSize();
}

void LBBeautifulSkinFilter::setSharpness(float sharpness){
    combineTextureFilter->setSharpness(sharpness);
}